Gonzalo Alvis¶
Usar urbanpy para descargar datos de una ciudad
Los markdowns los hice para enterarme de que estaba haciendo.
Librerias¶
import warnings
import sys
import urbanpy as up
import pandas as pd
import plotly
import plotly.express as px
import plotly.graph_objects as go
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from tqdm.notebook import tqdm
import geopandas as gpd
sys.path.append("..")
warnings.filterwarnings("ignore")
tqdm.pandas()
Mapa¶
Descarga de OSM (open street maps) el mapa de la ciudad que especificas.
ciudad = up.download.nominatim_osm(
"Barcelona, España"
) # expected_position is 0 by default
ciudad.plot()
plt.show()
population data¶
Esta funcion consulta las bases de datos que hay de este pais (luego se filtrará).
Todo lo que tiene hdx se refiere al humanitarian data exchange (base de datos)
city_resources=up.download.search_hdx_dataset("Spain")
city_resources
| created | name | population | size_mb | url | |
|---|---|---|---|---|---|
| id | |||||
| 0 | 2020-03-04 | esp_general_2020_csv.zip | Overall population density | 222.35 | https://data.humdata.org/dataset/80d0519e-0eaf... |
| 8 | 2019-09-23 | esp_children_under_five_2020_csv.zip | Children (ages 0-5) | 221.25 | https://data.humdata.org/dataset/80d0519e-0eaf... |
| 9 | 2019-09-23 | esp_elderly_60_plus_2020_csv.zip | Elderly (ages 60+) | 222.65 | https://data.humdata.org/dataset/80d0519e-0eaf... |
| 10 | 2019-09-23 | esp_men_2020_csv.zip | Men | 222.07 | https://data.humdata.org/dataset/80d0519e-0eaf... |
| 11 | 2019-09-23 | esp_women_2020_csv.zip | Women | 222.16 | https://data.humdata.org/dataset/80d0519e-0eaf... |
| 12 | 2019-09-23 | esp_women_of_reproductive_age_15_49_2020_csv.zip | Women of reproductive age (ages 15-49) | 222.44 | https://data.humdata.org/dataset/80d0519e-0eaf... |
pop_spn=up.download.get_hdx_dataset(city_resources,0)
pop_spn.head()
| longitude | latitude | esp_general_2020 | |
|---|---|---|---|
| 0 | -1.269444 | 44.0 | 0.673977 |
| 1 | -1.268611 | 44.0 | 0.673977 |
| 2 | -1.160833 | 44.0 | 0.536216 |
| 3 | -1.158333 | 44.0 | 0.536216 |
| 4 | -1.006944 | 44.0 | 0.539089 |
Conversion a puntos y hexagonos¶
Ok, esta parte hace el filtro de la informacion para la ciudad. O sea, la informacion es de españa, pero esta parte lo que hace es filtrar de acuerdo a las dimensiones de la ciudad (Barcelona). Ademas, crea los hexagonos (esta figura es perfecta para la ubicacion espacial porque esta igual de cerca que todos sus vecinos.)
La resolucion influencia en el numero de hexagonos. La diferencia entre 8 y 9 en el numero de hexagonos me parece destacable, para barcelona por lo menos. En el demo se ve que usa el 7 para quito.
pop_ba=up.geom.filter_population(pop_spn,ciudad)
pop_ba.plot()
<Axes: >
#11 es demasiado detalle, ademas, con mas resolucion tarda mas de 2 segundos. El ideal es un punto entre 9 y 8. Usare el 8
hex_ba=up.geom.gen_hexagons(resolution=8,city=ciudad)
hex_ba.shape
(144, 2)
hex_ba.plot()
<Axes: >
Mergeando layers¶
El mergeo se encarga de cruzar las bases, o sea, colorear los hexagonos con la informacion de la poblacion de barcelona españa por ejemplo. En este mapa en particular, se ve que las zonas en gris, o con baja densidad poblacional son las areas verdes como observatorios, montañas o atracciones de ese estilo.
pop_ba.head()
| longitude | latitude | esp_general_2020 | geometry | |
|---|---|---|---|---|
| 9828392 | 2.052500 | 41.467778 | 11.406598 | POINT (2.05250 41.46778) |
| 9828393 | 2.053333 | 41.467778 | 5.703299 | POINT (2.05333 41.46778) |
| 9828394 | 2.053611 | 41.467778 | 5.703299 | POINT (2.05361 41.46778) |
| 9828395 | 2.053889 | 41.467778 | 5.703299 | POINT (2.05389 41.46778) |
| 9828396 | 2.054167 | 41.467778 | 5.703299 | POINT (2.05417 41.46778) |
hex_ba=up.geom.merge_shape_hex(hex_ba,pop_ba,agg={"esp_general_2020":"sum"})
hex_ba.plot(
"esp_general_2020", legend=True, missing_kwds={"color": "grey"}
)
plt.title("Barcelona - H3 res: 8")
plt.axis(False)
plt.tight_layout()
fs, metadata = up.download.overpass(
type_of_data="node",
mask=ciudad,
query={
"amenity": ["marketplace"],
"shop": [
"supermarket",
"kiosk",
"mall",
"convenience",
"butcher",
"greengrocer",
],
},
)
El demo en este momento consulta el API de overpass para obtener POI (puntos de interes). Dejó un link a la wiki de OSM. He probado una query para universidades en Barcelona
fs, metadata = up.download.overpass(
type_of_data="node",
mask=ciudad,
query={
"amenity": ["university"],
},
)
Aca busco si estan los nombres de las universidades para el grafico de mas tarde
for i in fs['tags']:
try:
print(i['name'])
except:
print(i)
Escola de Noves Tecnologies Interactives Facultat de Física Facultat de Química Facultat de Farmàcia Facultat d'Economia i Empresa Facultat de Biologia Col·legi Major Penyafort IGEMA Universitat de Barcelona School of Economics Acadèmia SOL Alberg Sea Point Hostel UPC Facultat de Nàutica de Barcelona Escola Superior de Relacions Públiques EAE Bussines School Acadèmia ASES Escola Universitària Salesiana de Sarrià EUSS Universitat Pompeu Fabra–Campus del Poblenou INSA. Business, Marketing & Communication School Arquitectura la Salle Enginyeria i Arquitectura la Salle Academia CEUS IEEE BCN Student branch Residencia Universitaria Torre Girona IESE Business School Institut Químic de Sarrià Enginyeria i Arquitectura La Salle ISDE Law School Facultat d'Educació Facultat de Psicologia
#numero de resultados de la consulta, en este caso numero de universidades que overpass encuentra en Barcelona
fs.shape
(29, 7)
Entiendo que esta parte se encarga de abrir un servidor de osrm (open source routing machine) en Docker (no lo consiguio, tuve que hacerlo manualmente).
Habiendo entrado en el directorio del windows_download
.\windows_download.ps1 osrm_routing_server spain europe foot
El servidor encontrará la distancia entre cada hexagono y el POI mas cercano. Por eso tiene 144 consultas en la casilla de travel_times, porque son 144 hexagonos
up.routing.start_osrm_server("spain", "europe", "foot")
Starting server ... Server was started succesfully
hex_barcelona_access = up.accessibility.travel_times(hex_ba, fs, "university")
hex_barcelona_access.head()
0%| | 0/144 [00:00<?, ?it/s]
| hex | geometry | esp_general_2020 | lon | lat | nearest_university_ix | distance_to_nearest_university | duration_to_nearest_university | duration_to_nearest_university_label | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 883944635dfffff | POLYGON ((2.05686 41.43592, 2.05569 41.43116, ... | 172.877483 | 2.061539 | 41.433011 | 23 | 9.0403 | 108.820000 | 90-120 |
| 1 | 8839446309fffff | POLYGON ((2.05333 41.42163, 2.05215 41.41687, ... | 350.330407 | 2.058001 | 41.418721 | 23 | 7.3502 | 88.538333 | 60-90 |
| 2 | 8839446355fffff | POLYGON ((2.06036 41.42825, 2.05918 41.42348, ... | 34.575497 | 2.065034 | 41.425339 | 23 | 7.3271 | 88.260000 | 60-90 |
| 3 | 8839446289fffff | POLYGON ((2.17635 41.46054, 2.17516 41.45577, ... | 7157.127811 | 2.181025 | 41.457623 | 27 | 5.1782 | 62.220000 | 60-90 |
| 4 | 8839446ad3fffff | POLYGON ((2.12678 41.32632, 2.12560 41.32155, ... | 8435.343412 | 2.131452 | 41.323400 | 12 | 7.2841 | 88.486667 | 60-90 |
up.routing.stop_osrm_server("spain", "europe", "foot")
Server was stoped succesfully
Interactive map¶
plotly.offline.init_notebook_mode()
El mapa del demo para ver la demografia (con plotly). Le agregué el zoom porque era incomodo de ver
fig = up.plotting.choropleth_map(
hex_ba,
"esp_general_2020",
title="Estimated Spain Population - 2020",
width=800,
height=800,
)
# Make space for the title
fig.update_layout(margin=dict(l=0, r=0, b=0),mapbox=dict(zoom=11))
fig.show()
aca ordena los tiempos de viaje en categorias, para hacer el mapa para visualizar barcelona y los tiempos promedio que tardan para llegar a la universidad mas cercana a pie
# Get ordered category labels
category_orders = (
hex_barcelona_access["duration_to_nearest_university_label"].unique().sort_values()
)
category_orders.categories
Index(['0-15', '15-30', '30-45', '45-60', '60-90', '90-120'], dtype='object')
hex_barcelona_access_filtered_pop = hex_barcelona_access.query(
"esp_general_2020 > 0"
).reset_index(drop=True)
fig = up.plotting.choropleth_map(
hex_barcelona_access_filtered_pop,
color_column="duration_to_nearest_university_label",
color_discrete_sequence=px.colors.sequential.Plasma_r,
category_orders={"duration_to_nearest_university_label": category_orders},
labels={"duration_to_nearest_university_label": "Minutes"},
title="Time to Nearest University (Walking Distance)",
width=800,
height=800,
)
# Make space for the title
fig.update_layout(margin=dict(l=0, r=0, b=0))
# Remove the hexagon outlines to make the map clearer
fig.update_traces(marker_line_width=0)
fs['name'] = fs['tags'].apply(lambda x: x.get('name', 'Unknown'))
fs['geometry'] = gpd.points_from_xy(fs['lon'], fs['lat'])
scatter_trace = go.Scattermapbox(
lat=fs['lat'],
lon=fs['lon'],
mode='markers',
marker=go.scattermapbox.Marker(
size=10,
color='blue',
opacity=0.7
),
text=fs['name'],
hoverinfo='text',
showlegend=False
)
fig.add_trace(scatter_trace)
fig.update_layout(
mapbox=dict(zoom=11)
)
fig.show()
Finalmente, mi mapa es de barcelona con los tiempos (en minutos) que toma llegar entre cada hexagono a la universidad mas cercana (a pie). Cada punto azul es una universidad, con su nombre.